#ifndef __ASM_EXCEPTION_H
#define __ASM_EXCEPTION_H

#include <dim-sum/linkage.h>
#include <asm/ptrace.h>

#ifndef __ASSEMBLY__

struct exception_spot {
	u64 regs[31];
	u64 sp;
	u64 pc;
	u64 pstate;
	u64 orig_x0;
	u64 syscallno;
};

struct fp_context
{
	u32 mvfr0;
	u32 mvfr1;
	u32 mvfr2;
	u32 fpcr;
	u32 fpsr;
	/**
	 * 仅仅针对32位寄存器
	 */
	u32 fpexc32;
	/**
	 * 32个128位浮点寄存器
	 */
	u64 fpregs[64];
};

#ifndef GET_IP
#define GET_IP(regs) ((regs)->pc)
#endif
#ifndef SET_IP
#define SET_IP(regs, val) (GET_IP(regs) = (val))
#endif

#ifndef GET_SP
#define GET_SP(regs) ((regs)->sp)
#endif

#ifndef SET_SP
#define SET_SP(regs, val) (GET_SP(regs) = (val))
#endif

#define user_mode(regs)	\
	(((regs)->pstate & PSR_MODE_MASK) == PSR_MODE_EL0t)

static inline unsigned long instruction_pointer(struct exception_spot *regs)
{
	return GET_IP(regs);
}
static inline void instruction_pointer_set(struct exception_spot *regs,
                                           unsigned long val)
{
	SET_IP(regs, val);
}

static inline unsigned long stack_pointer(struct exception_spot *regs)
{
	return GET_SP(regs);
}

static inline void stack_pointer_set(struct exception_spot *regs,
                                           unsigned long val)
{
	SET_SP(regs, val);
}

static inline struct exception_spot *current_exception_spot(void)
{
	register unsigned long es asm ("x28");
	return (struct exception_spot *)(es);
}

static inline void arch_set_execve_regs(struct exception_spot* regs, u64 pc, u64 sp)
{
	regs->sp = sp;
	regs->pc = pc;
	regs->pstate = PSR_MODE_EL0t;
}

#define __exception	__attribute__((section(".exception.text")))
#define __exception_irq_entry	__exception

asmlinkage void hung(unsigned long addr, unsigned esr);

#endif /* __ASSEMBLY__ */

#endif	/* __ASM_EXCEPTION_H */
